from typing import Optional, Tuple
import pandas as pd
from loguru import logger
from services.stock_index_service import StockIndexService
from services.futures_realtime_service import FuturesRealtimeService, IndexFutures
from services.basis_utils import BasisUtils
from services.futures_history_service import FuturesHistoryService


class BasisMonitorModel:
    
    def __init__(self):
        self.stock_index_service = StockIndexService()
        self.futures_realtime_service = FuturesRealtimeService()
        self.futures_history_service = FuturesHistoryService()
        
    def get_target_index_codes(self) -> list:
        return ["000016", "000300", "000905", "000852"]
    
    
    def fetch_data(self) -> Tuple[Optional[pd.DataFrame], Optional[pd.DataFrame]]:
        try:
            # 1. 获取指数数据并计算涨跌幅
            target_codes = self.get_target_index_codes()
            
            # 使用服务层方法获取包含涨跌计算的数据
            processed_df = self.stock_index_service.get_index_spot_data(target_codes)
            
            raw_index_data = None
            index_display_df = None
            if processed_df is not None and not processed_df.empty:
                raw_index_data = processed_df.copy()
                
                # 格式化显示数据
                display_df = processed_df.copy()
                display_df['price'] = display_df['price'].apply(lambda x: f"{float(x):.2f}" if pd.notna(x) else "0.00")
                display_df['change'] = display_df['change'].apply(lambda x: f"{float(x):.2f}" if pd.notna(x) else "0.00")
                display_df['change_pct'] = display_df['change_pct'].apply(lambda x: f"{float(x):.2f}%" if pd.notna(x) else "0.0%")
                
                display_df = display_df[['code', 'name', 'price', 'change', 'change_pct']]
                display_df.columns = ["代码", "名称", "价格", "涨跌额", "涨跌幅"]
                index_display_df = display_df

            # 2. 获取期货数据
            all_futures_df = pd.DataFrame()
            for futures in IndexFutures:
                try:
                    df = self.futures_realtime_service.get_realtime_data(futures)
                    if df is not None and not df.empty:
                        all_futures_df = pd.concat([all_futures_df, df], ignore_index=True)
                except Exception as e:
                    logger.error(f"Failed to get futures data for {futures.value}: {e}")
            
            futures_display_df = None
            if not all_futures_df.empty:
                display_df = all_futures_df[['symbol', 'trade', 'change', 'changepercent', 'expiry_date', 'days_to_expiry']].copy()
                display_df['trade'] = display_df['trade'].apply(lambda x: f"{x:.2f}")
                display_df['change'] = display_df['change'].apply(lambda x: f"{x:.2f}")
                display_df['changepercent'] = display_df['changepercent'].apply(lambda x: f"{x*100:.2f}%")
                display_df.columns = ["合约", "最新价格", "涨跌额", "涨跌幅", "到期日", "距离到期日"]
                
                if raw_index_data is not None:
                    spot_data = raw_index_data[['code', 'name', 'price']].copy()
                    spot_data.columns = ['代码', '名称', '价格']
                    spot_data['价格'] = spot_data['价格'].apply(lambda x: f"{float(x):.2f}")
                    
                    display_df = BasisUtils.add_basis_to_futures_data(spot_data, display_df)
                
                futures_display_df = display_df
            
            return index_display_df, futures_display_df

        except Exception as e:
            logger.exception(f"Error in data fetch task: {e}")
            return None, None

    def get_stock_index_service(self):
        return self.stock_index_service

    def get_futures_history_service(self):
        return self.futures_history_service